﻿using System.Buffers;
using ePipe;
using Letter.IO.Binary;
using Letter.Net;
using Letter.Net.Session;

namespace tcp_connection;

public class ATcpConnection : AConnection
{
    private const int PACK_HEAD_BYTES_LEN = 4;
    
    private int maxPackLength = int.MaxValue;
    private PackPart currentReadPart = PackPart.Head;
    private int currentReadLength = PACK_HEAD_BYTES_LEN;


    public override void OnActive()
    {
        this.ReadAsync();
    }

    private async void ReadAsync()
    {
        try
        {
            while (true)
            {
                var result = await this.Transport.Reader.ReadAsync();
                if (result.IsCanceled || result.IsCompleted)
                {
                    Console.WriteLine("读取完成");
                    break;
                }

                this.Read(result.Buffer);
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
        finally
        {
            this.Transport.Reader.Complete();
            this.Transport.Reader.CancelPendingRead();
        }
    }

    private void Read(ReadOnlySequence<byte> seg)
    {
        var reader = seg.ToBytesReader();
        while (reader.IsLengthEnough(this.currentReadLength))
        {
            if (this.currentReadPart == PackPart.Head)
            {
                this.currentReadLength = reader.ReadInt32BE();
                //Console.WriteLine("头：" + currentReadLength);
                if (this.currentReadLength > this.maxPackLength)
                {
                    throw new Exception("pack length error!" + currentReadLength);
                }

                this.currentReadPart = PackPart.Body;
            }
            else if (this.currentReadPart == PackPart.Body)
            {
                //Console.WriteLine("消息：" + buf.Length);
                OnMessage(reader.ReadBuffer(this.currentReadLength));

                this.currentReadLength = PACK_HEAD_BYTES_LEN;
                this.currentReadPart = PackPart.Head;
            }
        }

        this.Transport.Reader.AdvanceTo(reader.End);
    }

    protected virtual async void OnMessage(ReadOnlySequence<byte> buf)
    {
        
    }


    public void Write(byte[] bytes)
    {
        var buf = new ReadOnlySequence<byte>(bytes);
        this.InternalWrite(ref buf);
    }

    protected void InternalWrite(ref ReadOnlySequence<byte> buf)
    {
        var writer = this.Transport.Writer.ToBytesWriter();
        writer.WriteInt32BE((int)buf.Length);
        writer.WriteSequence(ref buf);
    }
    
    public ValueTask<FlushResult> FlushAsync()
    {
        return this.Transport.Writer.FlushAsync();
    }

    public override void OnException(Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }

     public override void OnInactive()
    {
        Console.WriteLine("连接断开");
    }

    enum PackPart : byte
    {
        Head,
        Body,
    }
}